<?php
namespace Demo\Controller;
use Think\Controller;
use Wechat\Wechat;

header("Content-type:text/html;charset=utf-8;");
class IndexController extends Controller{
    private $appid = 'wxb70359eb19266f10';
    private $appsecret = 'd05e862df76a7401e0b2af0f06e8eade';
    private $WechatAuth = '';
    private $access_token = '';
    private $weObj = '';
    public $open_id;
    public $wxuser;
    protected $tokenInfo; //获取access_token中所有返回值信息

    private $options = array(
                        'token'=>'ML168', //填写你设定的key
                        'appid'=>'wxb70359eb19266f10', //填写高级调用功能的app id, 请在微信开发模式后台查询
                        'appsecret'=>'d05e862df76a7401e0b2af0f06e8eade', //填写高级调用功能的密钥
                        'debug'=>true,
                        'logcallback'=>'logdebug',
                       );

    public function __construct(){
        parent::__construct();
        $options = $this->options;
        $weObj = new Wechat($options);
        $this->weObj = $weObj;
    }

    public function logdebug($content){
        $content = $content."\nREMOTE_ADDR：".$_SERVER['REMOTE_ADDR']."\nQUERY_STRING：".$_SERVER['QUERY_STRING'].'\n\n';

        $logSize = 10000;
        $log = 'Public/log.txt';

        if(file_exists($log) && filesize($log) > $logSize){
            unlink($log);
        }

        file_put_contents($log,date('H:i:s')." ".$content."\n",FILE_APPEND); // "\n" 用双引号，单引号不识别

        // file_put_contents('./log.txt',$text."\n",FILE_APPEND);    
    }

    public function index(){
        $weObj = $this->weObj;
        $type = $weObj->getRev()->getRevType();
        switch($type) {
            case Wechat::MSGTYPE_TEXT:
                    $weObj->text("hello, I'm wechat")->reply();
                    // $this->logdebug("发送给用户的信息："."hello, I'm wechat");
                    exit;
                    break;
            case Wechat::MSGTYPE_EVENT:
                    break;
            case Wechat::MSGTYPE_IMAGE:
                    break;
            default:
                    $weObj->text("help info")->reply();
        }
    }

    public function wxoauth(){
        $scope = 'snsapi_base';
        $code = isset($_GET['code'])?$_GET['code']:'';
        $token_time = isset($_SESSION['token_time'])?$_SESSION['token_time']:0;

        // 注意：对于已关注公众号的用户，如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页，
        // 即使是scope为snsapi_userinfo，也是静默授权，用户无感知。

        // 目前access_token的有效期通过返回的expire_in来传达，目前是7200秒之内的值。需在有效期内提前刷新
        // 如果距离最近一次获取access_token的时间 已超过1小时，调用refresh_token进行刷新，refresh_token有效期为30天
        // 服务器通过SessionID来读取Session的数据，但是一般浏览器传送的SessionID在浏览器关闭后就没有了
        // 如果cookie中设置的PHPSESSID过期时间超过24分钟(这里一般设为2小时)与服务器端session过期时间保持一致
        // 那么微信用户关闭网页后，下次再次打开，如果距离上次会话时间超过cookie中设置的PHPSESSID的过期时间，SessionID就将作废
        // 此时服务器端的session也早已过期被回收了
        // 解决方案：应该根据cookie中存放的openid从数据表中取refresh_token，并且距离上一次更新时间是超过2小时的(now_time - update_time > 7200)，
        //          则调用refresh_token 刷新access_token
        if(!$code && isset($_SESSION['open_id']) && isset($_SESSION['user_token']) && $token_time<time()-3600){ // 这种判断条件不适用实际情况！
            $options = array(
                    'token'=>$this->options["token"], //填写你设定的key
                    'appid'=>$this->options["appid"], //填写高级调用功能的app id
                    'appsecret'=>$this->options["appsecret"] //填写高级调用功能的密钥
            );
            $we_obj = new Wechat($options);

            // 事先根据用户的openid，将access_token refresh_token写入数据库，持久化存储
            // session默认24分钟失效，如果未设置过期时间
            // 实际处理方式：用cookie将openid保存在客户端，cookie过期时间设置长久一些
            // 下次微信用户进公众号，先从cookie中取openid值，再根据openid从数据库中取出refresh_token，再刷新access_token
            // 微信用户对公众号的openid是唯一且不变的，相当于微信用户登录公众号应用的用户账号
            // 因而用户首次进入公众号，获取到 access_token refresh_token openid等字段信息后，用cookie将openid存到微信客户端
            $refresh_token = $_SESSION['tokenInfo']['refresh_token'];

            $json = $we_obj->getOauthRefreshToken($refresh_token);
            $this->tokenInfo = $_SESSION['tokenInfo'] = $json; // 保存access_token中所有返回信息
            if (!$json) {
                unset($_SESSION['wx_redirect']);
                die('获取用户授权失败，请重新确认');
            }
            $_SESSION['open_id'] = $this->open_id = $json["openid"];
            $access_token = $json['access_token'];
            $_SESSION['user_token'] = $access_token;
            $_SESSION['token_time'] = time();

            $this->wxuser = $_SESSION['wxuser'];
        }

        // 如果code不存在 并且 session中已缓存openid和access_token 并且 距离最近一次获取access_token的时间未超过1小时
        // 则无需请求微信服务器获取新的access_token，直接从session缓存中获取
        if(!$code && isset($_SESSION['open_id']) && isset($_SESSION['user_token']) && $token_time>time()-3600)
        {
            if (!$this->wxuser) {
                $this->wxuser = $_SESSION['wxuser'];
            }
            $this->open_id = $_SESSION['open_id'];
            $this->tokenInfo = $_SESSION['tokenInfo'];
            return $this->open_id;
        }
        else
        {
            $options = array(
                    'token'=>$this->options["token"], //填写你设定的key
                    'appid'=>$this->options["appid"], //填写高级调用功能的app id
                    'appsecret'=>$this->options["appsecret"] //填写高级调用功能的密钥
            );
            $we_obj = new Wechat($options);

            // code说明 ： code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
            if ($code) {
                $json = $we_obj->getOauthAccessToken();
                $this->tokenInfo = $_SESSION['tokenInfo'] = $json; // 保存access_token中所有返回信息
                if (!$json) {
                    unset($_SESSION['wx_redirect']);
                    die('获取用户授权失败，请重新确认');
                }
                $_SESSION['open_id'] = $this->open_id = $json["openid"];
                $access_token = $json['access_token'];
                $_SESSION['user_token'] = $access_token;
                $_SESSION['token_time'] = time();

                session(array('expire'=>$json['expire_in'])); //设置缓存时间

                $userinfo = $we_obj->getUserInfo($this->open_id);
                if ($userinfo && !empty($userinfo['nickname'])) {
                    $this->wxuser = array(
                            'open_id'=>$this->open_id,
                            'nickname'=>$userinfo['nickname'],
                            'sex'=>intval($userinfo['sex']),
                            'location'=>$userinfo['province'].'-'.$userinfo['city'],
                            'avatar'=>$userinfo['headimgurl']
                    );
                } elseif (strstr($json['scope'],'snsapi_userinfo')!==false) {
                    $userinfo = $we_obj->getOauthUserinfo($access_token,$this->open_id);
                    if ($userinfo && !empty($userinfo['nickname'])) {
                        $this->wxuser = array(
                                'open_id'=>$this->open_id,
                                'nickname'=>$userinfo['nickname'],
                                'sex'=>intval($userinfo['sex']),
                                'location'=>$userinfo['province'].'-'.$userinfo['city'],
                                'avatar'=>$userinfo['headimgurl']
                        );
                    } else {
                        return $this->open_id;
                    }
                }
                if ($this->wxuser) {
                    $_SESSION['wxuser'] = $this->wxuser;
                    $_SESSION['open_id'] =  $json["openid"];
                    unset($_SESSION['wx_redirect']);
                    return $this->open_id;
                }
                $scope = 'snsapi_userinfo';
            }

            if ($scope=='snsapi_base') {
                $url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                $_SESSION['wx_redirect'] = $url;
            } else {
                $url = $_SESSION['wx_redirect'];
            }

            if (!$url) {
                unset($_SESSION['wx_redirect']);
                die('获取用户授权失败');
            }

            // 用户同意授权，获取code，并重定向到指定的url redirect_uri/?code=CODE&state=STATE,此时可通过$_GET['code'] 获取到code值
            $oauth_url = $we_obj->getOauthRedirect($url,"wxbase",$scope); 
            header('Location: ' . $oauth_url);
        }
    }

    public function getWxuser(){
        $this->wxoauth();
        dump($this->wxuser);
        dump($this->tokenInfo);
    }

}